package com.zzyl.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.base.ResponseResult;
import com.zzyl.dto.DeviceDetailDTO;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.QueryIotProductPageDTO;
import com.zzyl.entity.Device;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.IotService;
import com.zzyl.vo.DeviceVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class IotServiceImpl implements IotService {

    @Resource
    Client iotClient;

    @Resource
    AliIoTConfigProperties aliIoTConfigProperties;

    @Resource
    DeviceMapper deviceMapper;

    @Override
    public ResponseResult getProductInfo(QueryIotProductPageDTO dto) {
        QueryProductListRequest request = new QueryProductListRequest();
        request.setCurrentPage(dto.getCurrentPage());
        request.setPageSize(dto.getPageSize());
        //公共实例
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        try {
            //分页查询公共实例下的产品
            QueryProductListResponse response = iotClient.queryProductList(request);
            QueryProductListResponseBody.QueryProductListResponseBodyData data = response.getBody().getData();
            String jsonString = JSONObject.toJSONString(data);
            log.info("获取所有产品{}", jsonString);
            return ResponseResult.success(data);
        } catch (Exception e) {
            log.error("获取所有产品失败", e);
            throw new RuntimeException("获取所有产品失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult registerDevice(DeviceDto deviceDto) {

        //校验是否有数据
        Device distinctDevice = new Device();
        distinctDevice.setDeviceName(deviceDto.getDeviceName());
        distinctDevice.setProductKey(deviceDto.getProductKey());
        long count = deviceMapper.count(distinctDevice);
        if (count > 0) {
            return ResponseResult.error("该设备已经绑定老人或者位置");
        }

        //1.注册云平台设备
        //1.1 创建注册设备参数对象
        RegisterDeviceRequest request = deviceDto.getRegisterDeviceRequest();
        //1.2 设置产品key,设备名称以及设备备注名称
        request.setProductKey(deviceDto.getProductKey());
        request.setNickname(deviceDto.getNickname());
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        RegisterDeviceResponse response;
        try {
            response = iotClient.registerDevice(request);
            //2.判断是否注册成功
            if (!response.getBody().getSuccess()) {
                //注册失败
                return ResponseResult.error(response.getBody().getErrorMessage());
            }
        } catch (Exception e) {
            log.error("注册设备失败", e);
            throw new RuntimeException("注册设备失败");
        }
        //通过产品key查询产品名称
        QueryProductRequest productRequest = new QueryProductRequest();
        productRequest.setProductKey(deviceDto.getProductKey());
        productRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        try {
            QueryProductResponse productResponse = iotClient.queryProduct(productRequest);
            deviceDto.setProductName(productResponse.getBody().getData().getProductName());
        } catch (Exception e) {
            log.error("查询产品失败", e);
            throw new RuntimeException("查询产品失败");
        }
        //3.插入设备表
        Device device = new Device();
        BeanUtils.copyProperties(deviceDto, device);
        device.setProduceName(deviceDto.getProductName());
        device.setDeviceId(response.getBody().getData().getIotId());
        device.setNoteName(deviceDto.getNickname());
        device.setProductId(deviceDto.getProductKey());
        device.setProduceName(deviceDto.getProductName());
        device.setBindingLocation(deviceDto.getBindingLocation().toString());
        device.setCreateTime(LocalDateTime.now());
        device.setUpdateTime(LocalDateTime.now());
        try {
            int insert = deviceMapper.insert(device);
            if (insert <= 0) {
                DeleteDeviceRequest delRequest = new DeleteDeviceRequest();
                delRequest.setProductKey(deviceDto.getProductKey());
                delRequest.setDeviceName(deviceDto.getDeviceName());
                delRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
                iotClient.deleteDevice(delRequest);
                return ResponseResult.error("设备注册失败");
            }
            log.info("插入设备数据 = {}", insert);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return ResponseResult.success();
    }

    @Override
    public ResponseResult queryDevice(QueryIotProductPageDTO dto) {

        PageHelper.startPage(dto.getCurrentPage(), dto.getPageSize());
        List<DeviceVo> deviceList = deviceMapper.queryByProductKey(dto.getProductKey());
        if (Objects.isNull(deviceList)) {
            return ResponseResult.success("暂无数据");
        }

        BatchQueryDeviceDetailRequest request = new BatchQueryDeviceDetailRequest();
        request.setProductKey(dto.getProductKey());
        List<String> deviceNames = deviceList.stream().map(DeviceVo::getDeviceName).collect(Collectors.toList());
        request.setDeviceName(deviceNames);
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        try {
            //查询阿里云平台的设备详情
            BatchQueryDeviceDetailResponse response = iotClient.batchQueryDeviceDetail(request);
            List<BatchQueryDeviceDetailResponseBody.BatchQueryDeviceDetailResponseBodyDataData> data = response
                    .getBody().getData().getData();
            //把数据转成map
            Map<String, BatchQueryDeviceDetailResponseBody.BatchQueryDeviceDetailResponseBodyDataData> collect = data.stream().collect(Collectors.toMap(BatchQueryDeviceDetailResponseBody
                    .BatchQueryDeviceDetailResponseBodyDataData::getDeviceName, v -> v));
            //通过key取map中的NodeType
            deviceList.forEach(deviceVo -> BeanUtils.copyProperties(collect.get(deviceVo.getDeviceName()), deviceVo));
        } catch (Exception e) {
            log.error("查询设备详情失败", e);
        }

        return ResponseResult.success(PageResponse.of(deviceList));
    }

    @Override
    public ResponseResult queryDeviceDetail(DeviceDetailDTO dto) {
        DeviceVo deviceVo = deviceMapper.queryDeviceDetail(dto.getIotId(), dto.getProductKey());
        QueryDeviceDetailRequest request = new QueryDeviceDetailRequest();
        request.setIotId(dto.getIotId());
        request.setProductKey(dto.getProductKey());
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        try {
            QueryDeviceDetailResponse deviceDetail = iotClient.queryDeviceDetail(request);
            QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData data = deviceDetail.getBody().getData();
            BeanUtils.copyProperties(data, deviceVo);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return ResponseResult.success(deviceVo);
    }

    @Override
    public ResponseResult queryThingModelPublished(DeviceDetailDTO dto) {
        QueryThingModelPublishedRequest request = new QueryThingModelPublishedRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setProductKey(dto.getProductKey());

        try {
            QueryThingModelPublishedResponse response = iotClient.queryThingModelPublished(request);
            QueryThingModelPublishedResponseBody.QueryThingModelPublishedResponseBodyData data = response.getBody().getData();
            return ResponseResult.success(data);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public ResponseResult queryDevicePropertyStatus(DeviceDto dto) {
        QueryDevicePropertyStatusRequest request = new QueryDevicePropertyStatusRequest();
        request.setDeviceName(dto.getDeviceName());
        request.setProductKey(dto.getProductKey());
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        try {
            QueryDevicePropertyStatusResponse response = iotClient.queryDevicePropertyStatus(request);
            QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData data = response.getBody().getData();
            return ResponseResult.success(data);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public ResponseResult updateDevice(DeviceDto dto) {

        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        List<BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo> list
                = new ArrayList<>();
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo pojo
                = new BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo();

        pojo.setNickname(dto.getNickname());
        pojo.setDeviceName(dto.getDeviceName());
        pojo.setIotId(dto.getIotId());
        pojo.setProductKey(dto.getProductKey());
        list.add(pojo);
        request.setDeviceNicknameInfo(list);
        Device device = new Device();
        BeanUtils.copyProperties(dto, device);
        device.setNoteName(dto.getNickname());
        deviceMapper.update(device);
        try {
            iotClient.batchUpdateDeviceNickname(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return ResponseResult.success();
    }

    @Override
    public ResponseResult deleteDevice(DeviceDetailDTO dto) {
        int i = deviceMapper.deleteByIotIdAndProductKey(dto.getIotId(), dto.getProductKey());
        return ResponseResult.success();
    }
}
